package com.example.bpmn.delegate;

import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import com.example.bpmn.domain.OrderStatus;
import com.example.bpmn.domain.DeliveryStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class OrderProcessDelegate implements JavaDelegate {
    
    private static final Object MERGE_LOCK = new Object();
    private final RuntimeService runtimeService;

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        String taskDefinitionKey = execution.getCurrentActivityId();
        switch (taskDefinitionKey) {
            case "Task_OrderMerge":
                mergeOrders(execution);
                break;
            case "Task_OrderSplit":
                splitOrder(execution);
                break;
            case "Task_SplitWarehouse":
                splitWarehouse(execution);
                break;
            case "Task_RiskCheck":
                checkRisk(execution);
                break;
            default:
                log.warn("未知的任务类型: {}", taskDefinitionKey);
        }
    }

    private void mergeOrders(DelegateExecution execution) throws Exception {
        String businessKey = execution.getBusinessKey();
        
        synchronized (MERGE_LOCK) {
            try {
                log.info("开始合并订单, businessKey: {}", businessKey);
                
                // 获取待合并订单
                List<Map<String, Object>> orders = getMockOrders();
                double totalAmount = calculateTotalAmount(orders);
                
                // 设置流程变量
                execution.setVariable("totalAmount", totalAmount);
                execution.setVariable("mergedOrders", orders);
                execution.setVariable("mergeTime", System.currentTimeMillis());
                
                // 更新订单状态
                for (Map<String, Object> order : orders) {
                    order.put("status", OrderStatus.MERGED);
                }
                
                // 设置运单状态
                execution.setVariable("deliveryStatus", DeliveryStatus.CREATED);
                
                // 启动运输流程
                if (!orders.isEmpty()) {
                    startDeliveryProcess(businessKey, orders, totalAmount);
                }
                
                log.info("订单合并完成: totalAmount={}, orderCount={}", 
                    totalAmount, orders.size());
                    
            } catch (Exception e) {
                log.error("订单合并失败: {}", e.getMessage(), e);
                throw e;
            }
        }
    }

    private void splitOrder(DelegateExecution execution) throws Exception {
        String businessKey = execution.getBusinessKey();
        log.info("开始订单拆分, businessKey: {}", businessKey);
        
        // 获取订单商品
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> orderItems = (List<Map<String, Object>>) 
            execution.getVariable("orderItems");
            
        // 判断是否需要供应商订单
        boolean needSupplierOrder = orderItems.stream()
            .anyMatch(item -> item.containsKey("supplierId"));
            
        execution.setVariable("needSupplierOrder", needSupplierOrder);
        
        // 拆分订单商品
        List<Map<String, Object>> userOrderItems = orderItems.stream()
            .filter(item -> !item.containsKey("supplierId"))
            .collect(Collectors.toList());
            
        List<Map<String, Object>> supplierOrderItems = orderItems.stream()
            .filter(item -> item.containsKey("supplierId"))
            .collect(Collectors.toList());
            
        execution.setVariable("userOrderItems", userOrderItems);
        execution.setVariable("supplierOrderItems", supplierOrderItems);
        
        log.info("订单拆分完成: needSupplierOrder={}, userItems={}, supplierItems={}", 
            needSupplierOrder, userOrderItems.size(), supplierOrderItems.size());
    }
    
    private void splitWarehouse(DelegateExecution execution) throws Exception {
        String businessKey = execution.getBusinessKey();
        log.info("SKU分仓处理, businessKey: {}", businessKey);
        
        // 模拟分仓逻辑
        execution.setVariable("warehouseCode", "WH_" + businessKey);
        execution.setVariable("splitTime", System.currentTimeMillis());
        
        log.info("分仓处理完成");
    }
    
    private void checkRisk(DelegateExecution execution) throws Exception {
        // 获取订单金额
        Double orderAmount = (Double) execution.getVariable("orderAmount");
        log.info("执行风控检查, 订单金额: {}", orderAmount);
        
        // 判断是否需要人工审核
        boolean needManualCheck = orderAmount != null && orderAmount > 10000;
        execution.setVariable("needManualCheck", needManualCheck);
        
        // 如果不需要人工审核，直接设置为通过
        if (!needManualCheck) {
            execution.setVariable("checkResult", "APPROVED");
        }
        
        log.info("风控检查完成: needManualCheck={}, checkResult={}", 
            needManualCheck, 
            execution.getVariable("checkResult"));
    }
    
    private void startDeliveryProcess(String businessKey, List<Map<String, Object>> orders, double totalAmount) {
        String deliveryId = "DEL_" + businessKey;
        Map<String, Object> variables = new HashMap<>();
        variables.put("mergedOrders", orders);
        variables.put("totalAmount", totalAmount);
        variables.put("orderItems", orders.stream()
            .flatMap(order -> ((List<Map<String, Object>>) order.get("items")).stream())
            .collect(Collectors.toList()));
        
        runtimeService.startProcessInstanceByKey(
            "deliveryProcess",
            deliveryId,
            variables
        );
        
        log.info("运输流程已启动: deliveryId={}, totalAmount={}", deliveryId, totalAmount);
    }

    private double calculateTotalAmount(List<Map<String, Object>> orders) {
        return orders.stream()
            .map(order -> (Double) order.get("amount"))
            .filter(amount -> amount != null)
            .mapToDouble(Double::doubleValue)
            .sum();
    }
    
    private List<Map<String, Object>> getMockOrders() {
        List<Map<String, Object>> orders = new ArrayList<>();
        
        Map<String, Object> order1 = new HashMap<>();
        order1.put("orderId", "SO_001");
        order1.put("amount", 150.0);
        order1.put("items", List.of(
            Map.of("skuId", "SKU001", "quantity", 2),
            Map.of("skuId", "SKU002", "quantity", 1)
        ));
        orders.add(order1);
        
        Map<String, Object> order2 = new HashMap<>();
        order2.put("orderId", "SO_002");
        order2.put("amount", 200.0);
        order2.put("items", List.of(
            Map.of("skuId", "SKU003", "quantity", 1)
        ));
        orders.add(order2);
        
        Map<String, Object> order3 = new HashMap<>();
        order3.put("orderId", "SO_003");
        order3.put("amount", 300.0);
        order3.put("items", List.of(
            Map.of("skuId", "SKU001", "quantity", 3),
            Map.of("skuId", "SKU004", "quantity", 2)
        ));
        orders.add(order3);
        
        return orders;
    }
} 